"""认证API视图"""
from datetime import datetime
from flask import request
from flask.views import MethodView
from flask_smorest import Blueprint, abort
from flask_jwt_extended import (
    create_access_token, 
    jwt_required, 
    get_jwt_identity,
    get_jwt
)
from flask_babel import gettext as _

from app.extensions import db
from app.models import User
from app.schemas.auth import LoginSchema, TokenSchema, ChangePasswordSchema
from app.schemas.user import UserSchema, UserCreateSchema
from app.responses import success_response, error_response
from app.status_codes import StatusCode, HttpStatusCode
from app.exceptions import (
    UserNotFoundException,
    UserAlreadyExistsException,
    AuthenticationException,
    ValidationException
)
from app.logs import logger

# 创建认证蓝图
auth_bp = Blueprint(
    'auth',
    __name__,
    url_prefix='/auth',
    description='用户认证相关API'
)


@auth_bp.route('/login')
class LoginView(MethodView):
    """用户登录视图"""
    
    @auth_bp.arguments(LoginSchema)
    @auth_bp.response(200, TokenSchema)
    @auth_bp.doc(
        summary="用户登录",
        description="用户使用用户名/邮箱和密码登录，返回JWT访问令牌"
    )
    def post(self, login_data):
        """用户登录"""
        username = login_data['username']
        password = login_data['password']
        
        # 查找用户（支持用户名或邮箱登录）
        user = User.query.filter(
            (User.username == username) | (User.email == username)
        ).first()
        
        if not user or not user.check_password(password):
            logger.warning(f"登录失败: 用户名/邮箱={username}, IP={request.remote_addr}")
            raise AuthenticationException(_("用户名或密码错误"))
        
        if not user.is_active:
            logger.warning(f"非活跃用户尝试登录: 用户ID={user.id}, IP={request.remote_addr}")
            raise AuthenticationException(_("账户已被禁用"))
        
        # 创建访问令牌
        access_token = create_access_token(identity=user.id)
        
        # 更新最后登录时间
        user.update_last_login()
        
        logger.info(f"用户登录成功: 用户ID={user.id}, 用户名={user.username}")
        
        token_data = {
            'access_token': access_token,
            'token_type': 'Bearer',
            'expires_in': 3600,  # 1小时
            'user': UserSchema().dump(user)
        }
        
        return success_response(
            data=token_data,
            message=_("登录成功")
        )


@auth_bp.route('/register')
class RegisterView(MethodView):
    """用户注册视图"""
    
    @auth_bp.arguments(UserCreateSchema)
    @auth_bp.response(201, UserSchema)
    @auth_bp.doc(
        summary="用户注册",
        description="创建新用户账户"
    )
    def post(self, user_data):
        """用户注册"""
        
        # 检查用户名是否已存在
        if User.query.filter_by(username=user_data['username']).first():
            raise UserAlreadyExistsException(_("用户名已存在"))
        
        # 检查邮箱是否已存在
        if User.query.filter_by(email=user_data['email']).first():
            raise UserAlreadyExistsException(_("邮箱已被注册"))
        
        # 创建新用户
        user = User(
            username=user_data['username'],
            email=user_data['email'],
            first_name=user_data.get('first_name'),
            last_name=user_data.get('last_name'),
            avatar_url=user_data.get('avatar_url')
        )
        user.password = user_data['password']
        
        try:
            db.session.add(user)
            db.session.commit()
            
            logger.info(f"新用户注册成功: 用户ID={user.id}, 用户名={user.username}")
            
            return success_response(
                data=UserSchema().dump(user),
                message=_("注册成功"),
                http_status=HttpStatusCode.CREATED
            )
            
        except Exception as e:
            db.session.rollback()
            logger.error(f"用户注册失败: {str(e)}")
            raise


@auth_bp.route('/profile')
class ProfileView(MethodView):
    """用户资料视图"""
    
    @jwt_required()
    @auth_bp.response(200, UserSchema)
    @auth_bp.doc(
        summary="获取用户资料",
        description="获取当前登录用户的资料信息"
    )
    def get(self):
        """获取当前用户资料"""
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user:
            raise UserNotFoundException(_("用户不存在"))
        
        return success_response(
            data=UserSchema().dump(user),
            message=_("获取用户资料成功")
        )


@auth_bp.route('/logout')
class LogoutView(MethodView):
    """用户登出视图"""
    
    @jwt_required()
    @auth_bp.response(200)
    @auth_bp.doc(
        summary="用户登出",
        description="用户登出，使当前令牌失效"
    )
    def post(self):
        """用户登出"""
        user_id = get_jwt_identity()
        jti = get_jwt()['jti']
        
        # 在实际项目中，这里应该将JWT加入黑名单
        # 这里仅作为示例返回成功响应
        
        logger.info(f"用户登出: 用户ID={user_id}, JTI={jti}")
        
        return success_response(
            message=_("登出成功")
        )


@auth_bp.route('/change-password')
class ChangePasswordView(MethodView):
    """修改密码视图"""
    
    @jwt_required()
    @auth_bp.arguments(ChangePasswordSchema)
    @auth_bp.response(200)
    @auth_bp.doc(
        summary="修改密码",
        description="用户修改登录密码"
    )
    def post(self, password_data):
        """修改密码"""
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user:
            raise UserNotFoundException(_("用户不存在"))
        
        # 验证原密码
        if not user.check_password(password_data['old_password']):
            raise AuthenticationException(_("原密码错误"))
        
        # 设置新密码
        user.password = password_data['new_password']
        
        try:
            db.session.commit()
            logger.info(f"用户修改密码成功: 用户ID={user.id}")
            
            return success_response(
                message=_("密码修改成功")
            )
            
        except Exception as e:
            db.session.rollback()
            logger.error(f"修改密码失败: {str(e)}")
            raise 